import { Message } from '@arco-design/web-react';
import { clearUserData } from '../services/auth';
import { getCookie } from '../services/auth';
import requestHandler from './requestHandler';

// 定义API响应类型
export interface ApiResponse<T> {
  code: number;
  message: string;
  data: T;
  timestamp: number;
  success: boolean;
}

/**
 * 通用请求函数
 * @param url 请求URL
 * @param options 请求选项
 * @returns Promise<ApiResponse<T>>
 */
export async function request<T>(url: string, options: RequestInit): Promise<ApiResponse<T>> {
  // 默认选项
  const defaultOptions: RequestInit = {
    headers: {
      'Content-Type': 'application/json',
    },
    credentials: 'include', // 确保发送Cookie
    ...options,
  };

  // 使用拦截器处理请求
  const processedOptions = requestHandler.handleRequest(url, defaultOptions);

  try {
    const response = await fetch(url, processedOptions);
    
    // 使用拦截器处理响应
    const processedResponse = await requestHandler.handleResponse(response, () => 
      request<T>(url, options)
    );
    
    const result: ApiResponse<T> = await processedResponse.json();
    return result;
  } catch (error) {
    console.error('请求失败:', error);
    throw error;
  }
}

// 存储待处理的请求队列
let pendingRequests: Array<() => void> = [];
// 是否正在刷新token
let isRefreshing = false;

/**
 * 创建请求拦截器
 * 处理token自动续期和过期情况
 */
class RequestInterceptor {
  /**
   * 处理请求
   * @param url 请求URL
   * @param config 请求配置
   * @returns 处理后的请求配置
   */
  handleRequest(_url: string, config: RequestInit): RequestInit {
    // 添加认证头
    const token = getCookie('ACCESS_TOKEN');
    if (token) {
      config.headers = {
        ...config.headers,
        'Authorization': `Bearer ${token}`
      };
    }
    
    return config;
  }

  /**
   * 处理响应
   * @param response 响应对象
   * @param retryOriginalRequest 重试原始请求的函数
   * @returns 处理后的响应
   */
  async handleResponse(response: Response, retryOriginalRequest: () => Promise<any>): Promise<Response> {
    // 如果是401未授权，尝试刷新token
    if (response.status === 401) {
      // 如果是刷新token的请求失败，直接登出
      if (response.url.includes('/api/auth/refresh')) {
        this.handleTokenRefreshFailure();
        throw new Error('Token已过期，请重新登录');
      }
      
      // 尝试刷新token
      const newToken = await this.refreshToken();
      if (newToken) {
        // 刷新成功，重试原始请求
        return retryOriginalRequest();
      } else {
        // 刷新失败，登出用户
        this.handleTokenRefreshFailure();
        throw new Error('Token已过期，请重新登录');
      }
    }
    
    return response;
  }

  /**
   * 刷新token
   * @returns 新的token或null
   */
  private async refreshToken(): Promise<string | null> {
    // 如果正在刷新token，将请求加入队列等待
    if (isRefreshing) {
      return new Promise((resolve) => {
        pendingRequests.push(() => resolve(this.refreshToken()));
      });
    }

    isRefreshing = true;
    
    try {
      const refreshToken = getCookie('REFRESH_TOKEN');
      if (!refreshToken) {
        return null;
      }

      const response = await fetch('/api/auth/refresh', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ refreshToken })
      });

      if (response.ok) {
        const result = await response.json();
        if (result.success) {
          // 刷新成功，执行待处理的请求
          pendingRequests.forEach(callback => callback());
          pendingRequests = [];
          return getCookie('ACCESS_TOKEN') || '';
        }
      }
      
      return null;
    } catch (error) {
      console.error('刷新token失败:', error);
      return null;
    } finally {
      isRefreshing = false;
    }
  }

  /**
   * 处理token刷新失败
   */
  private handleTokenRefreshFailure(): void {
    // 清除用户数据
    clearUserData();
    
    // 显示提示信息
    Message.error('登录已过期，请重新登录');
    
    // 跳转到登录页面
    setTimeout(() => {
      window.location.href = '/login';
    }, 1500);
  }
}

// 创建单例实例
const requestInterceptor = new RequestInterceptor();

export default requestInterceptor;